package com.draemoncode.weixindb.action;

import com.draemoncode.weixindb.constant.*;
import com.draemoncode.weixindb.content.EnvContent;
import com.draemoncode.weixindb.domain.*;
import com.draemoncode.weixindb.mvc.exception.BusiException;
import com.draemoncode.weixindb.repository.*;
import com.draemoncode.weixindb.server.CMessagePackage;
import com.draemoncode.weixindb.server.IAction;
import com.draemoncode.weixindb.service.MemberService;
import com.draemoncode.weixindb.util.JSONUtil;
import com.draemoncode.weixindb.util.ValueUtil;
import groovy.lang.Binding;
import groovy.lang.GroovyShell;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *
 * @author yangz
 * @date 2017/4/9
 *
 */
@Component
public class CalculatePodAction implements IAction<Map<String, BigDecimal>, String>{

    public final static String ACTION = "calculate";

    @Autowired
    private B_Calculate_CodeRepository b_calculate_codeRepository;

    @Autowired
    private B_MemberRepository b_memberRepository;

    @Autowired
    private B_XiaZhuRepository b_xiaZhuRepository;

    @Autowired
    private B_HongBaoRepository b_hongBaoRepository;

    @Autowired
    private B_PodRepository b_podRepository;

    @Autowired
    private B_Calculate_EnvRepository b_calculate_envRepository;

    @Autowired
    private MemberService memberService;

    @Autowired
    private B_AutoMessage_TemplateRepository b_autoMessage_templateRepository;

    private String ENV_POD = "ENV_POD";

    @Override
    public Boolean shoudProcess(String action) {
        return ACTION.equals(action);
    }


    @Override
    public Map<String, BigDecimal> busiExec() {
        B_Pod pod = b_podRepository.findByFlag(PodFlagConstant.ING);
        if(pod == null){
            throw new BusiException(HttpStatus.BAD_REQUEST.value(), "没人上庄");
        }
        EnvContent.put(ENV_POD, pod);
        B_Calculate_Code b_calculate_code = b_calculate_codeRepository.findByEnable(ValueConstant.ENABLE);
        if(b_calculate_code != null){
            List<B_Calculate_Env> envList = b_calculate_envRepository.findByCalculateCode(b_calculate_code.getId());
            List<B_XiaZhu> xiaZhuList = b_xiaZhuRepository.findByPod_id(pod.getId());
            List<B_HongBao> hongBaoList = b_hongBaoRepository.findByPod_id(pod.getId());
            B_Member zhuang = b_memberRepository.findByIdForUpdate(pod.getZhuang_id());
            List<B_Member> podMemberList = getPodMemberList(xiaZhuList);
            Map<String, Object> mergeZhuang = mergeZhuang(zhuang, pod, hongBaoList);
            List<Map<String, Object>> mergeXianList = mergeXianList(podMemberList, xiaZhuList, hongBaoList);
            Binding binding = bindingEnv(envList, mergeZhuang, mergeXianList);
            Map<Integer, BigDecimal> settle = groovySettle(binding, b_calculate_code.getCalculate_code());
            Map<String, BigDecimal> result = saveSettle(pod, podMemberList, zhuang, settle);
            pod.setFlag(PodFlagConstant.OK);
            pod.setSuccess_result(JSONUtil.toJson(result));
            b_podRepository.save(pod);
            return result;
        }else{
            throw new BusiException(HttpStatus.BAD_REQUEST.value(), "请设定玩法");
        }
    }

    @Override
    public String uiExec(Map<String, BigDecimal> busiResult) {
        Map<String, BigDecimal> map = new HashMap<>();
        map.putAll(busiResult);
        B_AutoMessage_Template b_autoMessage_template = b_autoMessage_templateRepository.findByFlag(AutoMessageConstant.CALULATE_TEMPLATE);
        String template = b_autoMessage_template.getTemplate();
        StringBuilder sb = new StringBuilder();
        String head = template.substring(0, template.indexOf("{"));
        String loop = template.substring(template.indexOf("{") + 1, template.indexOf("}"));
        String foot = template.substring(template.indexOf("}") + 1, template.length());
        sb.append(head);
        for (Map.Entry<String, BigDecimal> item : map.entrySet()) {
            String itemStr = loop.replace(AutoMessageKeyConstant.XIAN_JIA_KEY, item.getKey()).replace(AutoMessageKeyConstant.XIAN_WL, ValueUtil.formatMoney(item.getValue()));
            sb.append(itemStr);
        }
        sb.append(foot);
        return sb.toString();
    }

    @Override
    public CMessagePackage buildResponse(Map<String, BigDecimal> busiResult, String uiResult) {
        CMessagePackage response = new CMessagePackage(MessagePackageTypeConstant.RESPONSE_CACULATE_MESSAGE);
        B_Pod pod = (B_Pod) EnvContent.get(ENV_POD);
        response.setSyncid(pod.getId());
        response.getMsg().put(ShangZhuangFieldConstant.RESPONSE_SHOW_CONTENT, uiResult);
        return response;
    }


    private Map<String, BigDecimal> saveSettle(B_Pod b_pod, List<B_Member> xianList, B_Member zhuang, Map<Integer, BigDecimal> settle){
        Map<String, BigDecimal> result = new HashMap<>();
        for (Map.Entry<Integer, BigDecimal> item : settle.entrySet()){
            if(zhuang.getId().equals(item.getKey())){
                memberService.changeAccountByPod(zhuang, item.getValue(), b_pod.getId());
                result.put(zhuang.getName(), item.getValue());
            }else{
                B_Member xian = null;
                for (B_Member b_member : xianList) {
                    if(b_member.getId().equals(item.getKey())){
                        xian = b_member;
                        break;
                    }
                }
                Assert.notNull(xian, "xian is null");
                memberService.changeAccountByPod(xian, item.getValue(), b_pod.getId());
                result.put(xian.getName(), item.getValue());
            }
        }
        return result;
    }

    private Map<Integer, BigDecimal> groovySettle(Binding binding, String code){
        GroovyShell shell = new GroovyShell(binding);
        Map<Integer, BigDecimal> result = (Map<Integer, BigDecimal>) shell.evaluate(code);
        return result;
    }

    private Map<String, Object> mergeZhuang(B_Member b_member, B_Pod b_pod, List<B_HongBao> hongBaoList){
        Map<String, Object> result = new HashMap<>();
        result.put("id", b_member.getId());
        result.put("account", b_member.getMoney());
        result.put("all", b_pod.getZhuang_money());
        result.put("num", getNum(b_member.getId(), hongBaoList));
        return result;
    }

    private List<Map<String, Object>> mergeXianList(List<B_Member> memberList, List<B_XiaZhu> xiaZhuList, List<B_HongBao> hongBaoList){
        List<Map<String, Object>> result = new ArrayList<>();
        for (B_Member b_member : memberList) {
            Map<String, Object> map = new HashMap<>();
            map.put("id", b_member.getId());
            map.put("account", b_member.getMoney());
            map.put("zhu", getZhu(b_member.getId(), xiaZhuList));
            map.put("num", getNum(b_member.getId(), hongBaoList));
            result.add(map);
        }
        return result;
    }

    private String getZhu(Integer id, List<B_XiaZhu> xiaZhuList){
        for (B_XiaZhu b_xiaZhu : xiaZhuList) {
            if(id.equals(b_xiaZhu.getMember_id())){
                return ValueUtil.toString(b_xiaZhu.getXia_zhu());
            }
        }
        throw new BusiException("没有下注信息:" + id);
    }

    private String getNum(Integer id, List<B_HongBao> b_hongBaoList){
        for (B_HongBao b_hongBao : b_hongBaoList) {
            if(id.equals(b_hongBao.getMember_id())){
                return ValueUtil.toString(b_hongBao.getMoney());
            }
        }
        B_HongBao b_hongBao = b_hongBaoList.get(b_hongBaoList.size() - 1);
        return ValueUtil.toString(b_hongBao.getMoney());
    }

    private List<B_Member> getPodMemberList(List<B_XiaZhu> xiaZhuList){
        List<B_Member> result = new ArrayList<>();
        for (B_XiaZhu b_xiaZhu : xiaZhuList) {
            B_Member member = b_memberRepository.findByIdForUpdate(b_xiaZhu.getMember_id());
            result.add(member);
        }
        return result;
    }

    private Binding bindingEnv(List<B_Calculate_Env> envList,Map<String, Object> zhuang, List<Map<String, Object>> xianList){
        Binding binding = new Binding();
        for (B_Calculate_Env b_calculate_env : envList) {
            binding.setVariable(b_calculate_env.getCalculate_env_key(), b_calculate_env.getCalculate_env_value());
        }
        binding.setVariable("_zhuang", zhuang);
        binding.setVariable("_xianList", xianList);
        binding.setVariable("_result", new HashMap<>());
        return binding;
    }
}
